package com.zhu.utils;

import com.alibaba.fastjson.JSONObject;
import com.zhu.vo.ResVO;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

public class DailyAverageCalculator {

    private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    /**
     * 计算指定字段每日平均值，输入为 List<JSONObject>，其中每个 JSONObject 含 "time" 和 "value" 字段，
     * 其中 "value" 是字符串形式的JSON数组，数组里有一个对象。
     *
     * @param dataList     List<JSONObject>，输入数据列表
     * @param fieldNames   指定统计字段名列表，比如["u", "i1"]
     * @param startDateStr 起始日期字符串，格式yyyy-MM-dd
     * @param endDateStr   结束日期字符串，格式yyyy-MM-dd
     * @return List<Map < String, Object>>，每天的日期和均值
     */
    public static List<Map<String, Object>> calculateDailyAverage(
            List<ResVO> dataList,
            List<String> fieldNames,
            String startDateStr,
            String endDateStr) {

        LocalDate startDate = LocalDate.parse(startDateStr, DATE_FORMATTER);
        LocalDate endDate = LocalDate.parse(endDateStr, DATE_FORMATTER);

        // 初始化每一天的每一天的字段值为0
        Map<LocalDate, Map<String, Integer>> dailyCounts = new HashMap<>();
        Map<LocalDate, Map<String, Double>> dailySums = new HashMap<>();

        for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
            Map<String, Integer> counts = new HashMap<>();
            Map<String, Double> sums = new HashMap<>();
            for (String fieldName : fieldNames) {
                counts.put(fieldName, 0);
                sums.put(fieldName, 0.0);
            }
            dailyCounts.put(date, counts);
            dailySums.put(date, sums);
        }

        for (ResVO record : dataList) {
            String timeStr = record.getTime();
            String valueStr = record.getValue();

            if (timeStr == null || valueStr == null) {
                continue;
            }
            LocalDate date;
            try {
                date = LocalDate.parse(timeStr, DATETIME_FORMATTER);
            } catch (Exception e) {
                // 时间格式不正确，跳过
                continue;
            }

            if (date.isBefore(startDate) || date.isAfter(endDate)) {
                continue;
            }

            // valueStr 是数组字符串，解析成 List<JSONObject>
            List<JSONObject> valueList;
            try {
                valueList = JSONObject.parseArray(valueStr, JSONObject.class);
            } catch (Exception e) {
                // 解析失败，跳过
                continue;
            }
            if (valueList.isEmpty()) {
                continue;
            }

            JSONObject valueObj = valueList.get(0);
            Map<String, Integer> counts = dailyCounts.get(date);
            Map<String, Double> sums = dailySums.get(date);
            for (String fieldName : fieldNames) {
                if (!valueObj.containsKey(fieldName)) {
                    continue;
                }
                Object fieldValueObj = valueObj.get(fieldName);
                double fieldValue = fieldValueObj != null ? Double.parseDouble(fieldValueObj.toString()) : 0.0;
                sums.put(fieldName, sums.get(fieldName) + fieldValue);
                counts.put(fieldName, counts.get(fieldName) + 1);
            }
        }

        List<Map<String, Object>> result = new ArrayList<>();
        for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
            Map<String, Integer> counts = dailyCounts.get(date);
            Map<String, Double> sums = dailySums.get(date);
            final Map<String, Object> objectObjectHashMap = new HashMap<>();
            objectObjectHashMap.put("time", date.format(DATE_FORMATTER));
            for (String fieldName : fieldNames) {
                int count = counts.get(fieldName);
                double sum = sums.get(fieldName);
                double avg = count > 0 ? sum / count : 0.0;
                BigDecimal bd = BigDecimal.valueOf(avg);
                bd = bd.setScale(5, RoundingMode.HALF_UP);
                objectObjectHashMap.put(fieldName, bd.doubleValue());
            }
            result.add(objectObjectHashMap);
        }
        return result;
    }


    /**
     * 计算指定字段的每日平均值，输入数据为 List<JSONObject>，value字段是字符串形式的单个json对象
     *
     * @param dataList     List<JSONObject>，每个JSONObject包含"time"、"value"字段
     * @param fieldNames   要统计的字段名，如 "open_voltage"
     * @param startDateStr 开始日期字符串，格式 yyyy-MM-dd
     * @param endDateStr   结束日期字符串，格式 yyyy-MM-dd
     * @return List<Map < String, Object>> 每天时间和平均值
     */
    public static List<Map<String, Object>> calculateDailyAverage1(
            List<ResVO> dataList,
            List<String> fieldNames,
            String startDateStr,
            String endDateStr) {

        LocalDate startDate = LocalDate.parse(startDateStr, DATE_FORMATTER);
        LocalDate endDate = LocalDate.parse(endDateStr, DATE_FORMATTER);

        // 初始化每一天的每一天的字段值为0
        Map<LocalDate, Map<String, Integer>> dailyCounts = new HashMap<>();
        Map<LocalDate, Map<String, Double>> dailySums = new HashMap<>();

        for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
            Map<String, Integer> counts = new HashMap<>();
            Map<String, Double> sums = new HashMap<>();
            for (String fieldName : fieldNames) {
                counts.put(fieldName, 0);
                sums.put(fieldName, 0.0);
            }
            dailyCounts.put(date, counts);
            dailySums.put(date, sums);
        }

        for (ResVO record : dataList) {
            String timeStr = record.getTime();
            String valueStr = record.getValue();

            if (timeStr == null || valueStr == null) {
                continue;
            }
            LocalDate date;
            try {
                date = LocalDate.parse(timeStr, DATETIME_FORMATTER);
            } catch (Exception e) {
                // 时间格式不正确，跳过
                continue;
            }

            if (date.isBefore(startDate) || date.isAfter(endDate)) {
                continue;
            }

            // valueStr 是数组字符串，解析成 List<JSONObject>
            JSONObject valueObj;
            try {
                valueObj = JSONObject.parseObject(valueStr, JSONObject.class);
            } catch (Exception e) {
                // 解析失败，跳过
                continue;
            }
            Map<String, Integer> counts = dailyCounts.get(date);
            Map<String, Double> sums = dailySums.get(date);
            for (String fieldName : fieldNames) {
                if (!valueObj.containsKey(fieldName)) {
                    continue;
                }
                Object fieldValueObj = valueObj.get(fieldName);
                double fieldValue = fieldValueObj != null ? Double.parseDouble(fieldValueObj.toString()) : 0.0;
                sums.put(fieldName, sums.get(fieldName) + fieldValue);
                counts.put(fieldName, counts.get(fieldName) + 1);
            }
        }

        List<Map<String, Object>> result = new ArrayList<>();
        for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
            Map<String, Integer> counts = dailyCounts.get(date);
            Map<String, Double> sums = dailySums.get(date);
            final Map<String, Object> objectObjectHashMap = new HashMap<>();
            objectObjectHashMap.put("time", date.format(DATE_FORMATTER));
            for (String fieldName : fieldNames) {
                int count = counts.get(fieldName);
                double sum = sums.get(fieldName);
                double avg = count > 0 ? sum / count : 0.0;
                BigDecimal bd = BigDecimal.valueOf(avg);
                bd = bd.setScale(5, RoundingMode.HALF_UP);
                objectObjectHashMap.put(fieldName, bd.doubleValue());
            }
            result.add(objectObjectHashMap);
        }
        return result;
    }


    public static Map<String, List<Map<String, Object>>> calculateHourlyAverage(
            List<ResVO> data,
            List<String> fieldNames,
            String startDateStr,
            String endDateStr) {

        DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        LocalDate startDate = LocalDate.parse(startDateStr, DATE_FORMATTER);
        LocalDate endDate = LocalDate.parse(endDateStr, DATE_FORMATTER);

        Map<LocalDate, Map<Integer, List<Map<String, Double>>>> dailyHourlyValues = new HashMap<>();

        // 收集数据
        for (ResVO record : data) {
            String timeStr = record.getTime();
            String valueStr = record.getValue();

            if (timeStr == null || valueStr == null) {
                continue;
            }
            List<JSONObject> valueList;
            try {
                valueList = JSONObject.parseArray(valueStr, JSONObject.class);
            } catch (Exception e) {
                // 解析失败，跳过
                continue;
            }

            JSONObject valueObj = valueList.get(0);
            LocalDateTime dateTime;
            try {
                dateTime = LocalDateTime.parse(timeStr, DATETIME_FORMATTER);
            } catch (Exception e) {
                // 时间格式不正确，跳过
                continue;
            }

            LocalDate date = dateTime.toLocalDate();
            int hour = dateTime.getHour();

            if (date.isBefore(startDate) || date.isAfter(endDate)) {
                continue;
            }

            Map<String, Double> hourlyValues = new HashMap<>();
            for (String fieldName : fieldNames) {
                Object fieldValue1 = valueObj.get(fieldName);
                if (fieldValue1 != null) {
                    double fieldValue = Double.parseDouble(fieldValue1.toString());
                    hourlyValues.put(fieldName, fieldValue);
                }
            }

            dailyHourlyValues
                    .computeIfAbsent(date, k -> new HashMap<>())
                    .computeIfAbsent(hour, k -> new ArrayList<>())
                    .add(hourlyValues);
        }

        Map<String, List<Map<String, Object>>> result = new LinkedHashMap<>();

        // 计算每小时的平均值
        for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
            Map<Integer, List<Map<String, Double>>> hourlyMap = dailyHourlyValues.getOrDefault(date, Collections.emptyMap());

            List<Map<String, Object>> hourList = new ArrayList<>(24);
            for (int hour = 0; hour < 24; hour++) {  // 注意 hour 从 0 开始
                List<Map<String, Double>> values = hourlyMap.getOrDefault(hour, Collections.emptyList());

                Map<String, Object> hourResult = new HashMap<>();
                hourResult.put("time", hour);

                // 计算当前小时的字段值平均值
                for (String fieldName : fieldNames) {
                    double avgValue = calculateAverage(values, fieldName);
                    hourResult.put(fieldName, avgValue);
                }

                hourList.add(hourResult);
            }
            result.put(date.format(DATE_FORMATTER), hourList);
        }
        return result;
    }


    /**
     * 计算指定字段每日及每小时平均值，返回 Map<日期, List<{time:小时, fieldName:字段名, value:平均值}>>
     *
     * @param data         List<ResVO>，输入数据列表
     * @param fieldNames   List<String>，指定统计字段名列表，比如["u", "i1"]
     * @param startDateStr 起始日期字符串，格式yyyy-MM-dd
     * @param endDateStr   结束日期字符串，格式yyyy-MM-dd
     * @return Map<String, List < Map < String, Object>>>，外层key是日期，内层是24小时对应的时间和字段名及值
     */
    public static Map<String, List<Map<String, Object>>> calculateHourlyAverage1(
            List<ResVO> data,
            List<String> fieldNames,
            String startDateStr,
            String endDateStr) {

        DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        LocalDate startDate = LocalDate.parse(startDateStr, DATE_FORMATTER);
        LocalDate endDate = LocalDate.parse(endDateStr, DATE_FORMATTER);

        Map<LocalDate, Map<Integer, List<Map<String, Double>>>> dailyHourlyValues = new HashMap<>();

        // 收集数据
        for (ResVO record : data) {
            String timeStr = record.getTime();
            String valueStr = record.getValue();

            if (timeStr == null || valueStr == null) {
                continue;
            }
            JSONObject valueObj;
            try {
                valueObj = JSONObject.parseObject(valueStr, JSONObject.class);
            } catch (Exception e) {
                // 解析失败，跳过
                continue;
            }
            LocalDateTime dateTime;
            try {
                dateTime = LocalDateTime.parse(timeStr, DATETIME_FORMATTER);
            } catch (Exception e) {
                // 时间格式不正确，跳过
                continue;
            }

            LocalDate date = dateTime.toLocalDate();
            int hour = dateTime.getHour();

            if (date.isBefore(startDate) || date.isAfter(endDate)) {
                continue;
            }

            Map<String, Double> hourlyValues = new HashMap<>();
            for (String fieldName : fieldNames) {
                Object fieldValue1 = valueObj.get(fieldName);
                if (fieldValue1 != null) {
                    double fieldValue = Double.parseDouble(fieldValue1.toString());
                    hourlyValues.put(fieldName, fieldValue);
                }
            }

            dailyHourlyValues
                    .computeIfAbsent(date, k -> new HashMap<>())
                    .computeIfAbsent(hour, k -> new ArrayList<>())
                    .add(hourlyValues);
        }

        Map<String, List<Map<String, Object>>> result = new LinkedHashMap<>();

        // 计算每小时的平均值
        for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
            Map<Integer, List<Map<String, Double>>> hourlyMap = dailyHourlyValues.getOrDefault(date, Collections.emptyMap());

            List<Map<String, Object>> hourList = new ArrayList<>(24);
            for (int hour = 0; hour < 24; hour++) {  // 注意 hour 从 0 开始
                List<Map<String, Double>> values = hourlyMap.getOrDefault(hour, Collections.emptyList());

                Map<String, Object> hourResult = new HashMap<>();
                hourResult.put("time", hour);

                // 计算当前小时的字段值平均值
                for (String fieldName : fieldNames) {
                    double avgValue = calculateAverage(values, fieldName);
                    hourResult.put(fieldName, avgValue);
                }

                hourList.add(hourResult);
            }
            result.put(date.format(DATE_FORMATTER), hourList);
        }
        return result;
    }


    // 计算给定字段的平均值
    private static double calculateAverage(List<Map<String, Double>> values, String fieldName) {
        double sum = 0.0;
        int count = 0;
        for (Map<String, Double> valueMap : values) {
            Double value = valueMap.get(fieldName);
            if (value != null) {
                sum += value;
                count++;
            }
        }
        if (count == 0) {
            return 0.0; // 如果没有值，返回 0
        }
        double avg = sum / count;
        BigDecimal bd = BigDecimal.valueOf(avg);
        bd = bd.setScale(2, RoundingMode.HALF_UP); // 保留两位小数
        return bd.doubleValue();
    }
}

